home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / Editors / emacs / Emacs-1.14b1-sources / sources / mac-emacs-src / unexec.c < prev   
Encoding:
C/C++ Source or Header  |  1994-05-23  |  19.0 KB  |  740 lines  |  [TEXT/EMAC]

  1. /*
  2.  * Copyright (C) 1993, 1994 Marc Parmet.
  3.  * This file is part of the Macintosh port of GNU Emacs.
  4.  *
  5.  * GNU Emacs is distributed in the hope that it will be useful,
  6.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  8.  * GNU General Public License for more details.
  9.  */
  10.  
  11. #if defined(THINK_C)
  12. #include <MacHeaders>
  13. #else
  14. #include <Types.h>
  15. #include <Memory.h>
  16. #include <Quickdraw.h>
  17. #include <Windows.h>
  18. #include <Resources.h>
  19. #endif
  20.  
  21. #include "stdio.h"
  22. #include "config.h"
  23. #include "lisp.h"
  24. #include "buffer.h"
  25.  
  26. #if defined(THINKC)
  27. /* Pull out all the stops. */
  28. #pragma options(global_optimizer,gopt_induction,gopt_cse,gopt_loop,gopt_coloring)
  29. #endif
  30.  
  31. #define lisp_objects_in_buffer ((sizeof(struct buffer) - \
  32.     ((int)&((struct buffer *)0)->name)) / sizeof(int))
  33.  
  34. /* From ealloc.c */
  35. extern char *pure;
  36. extern int staticidx;
  37. extern char staticvec1[];
  38. #define staticvec ((Lisp_Object **) staticvec1)
  39.  
  40. /* These things are not protected with staticpro, not declared with DEFVAR_BOOL
  41.    or DEFVAR_INT, but we need to save and restore anyway. */
  42. extern struct buffer *current_buffer,*all_buffers;
  43. extern Lisp_Object selected_window;
  44. extern Lisp_Object global_map;
  45. extern Lisp_Object Qvariable_documentation;
  46. extern int unrch;
  47.  
  48. struct globals_to_save {
  49.     int *address;
  50.     char untagged,tag;
  51. } globals_to_save[] = {
  52.     { (int *)¤t_buffer,            1, Lisp_Buffer, },
  53.     { (int *)&all_buffers,                1, Lisp_Buffer, },
  54.     { (int *)&selected_window,            0, },
  55.     { (int *)&global_map,                0, },
  56.     { (int *)&Qvariable_documentation,    0, },
  57.     { (int *)&unrch,                    1, Lisp_Int,    },
  58. };
  59. #define nglobals_to_save (sizeof(globals_to_save) / sizeof(struct globals_to_save))
  60.  
  61. /* These three buffers are kept in static memory.  The first two also
  62.    have statically protected pointers pointing to them.  When we restore these
  63.    first two buffers, we must therefore restore them back into their static areas.
  64.    The third buffer is not statically protected, but here we can simply save and
  65.    restore its contents -- it contains no pointers. */
  66. extern struct buffer buffer_defaults,buffer_local_symbols,buffer_local_flags;
  67.  
  68. #define DUMP_VECTOR_MAX 130000
  69. static char *dump_vector;
  70. static int dump_free;
  71. static struct dumped_address_and_object {
  72.     Lisp_Object object;
  73.     int address;
  74. } *dumped_staticvec;
  75.  
  76. /* Offsets we store can be relative to three different bases, or can be absolute. */
  77. #define NO_SEGMENT            0
  78. #define DATA_SEGMENT        1
  79. #define PURE_SEGMENT        2
  80. #define DUMP_SEGMENT        3
  81.  
  82. #define SEGMENTBITS            2 /* We have four different segments, thus two bits. */
  83. #define OFFSETBITS            (VALBITS - SEGMENTBITS)
  84. #define NONOFFSETBITS        (32 - OFFSETBITS)
  85.  
  86. #define OFFSET_MASK            ((1 << OFFSETBITS) - 1)
  87. #define SEGMENT(X)            ((X >> OFFSETBITS) & ((1<<SEGMENTBITS)-1))
  88. #undef  OFFSET /* Defined in asm.h originally, delivered here by MacHeaders */
  89. #define OFFSET(X)            ((X << NONOFFSETBITS) >> NONOFFSETBITS)
  90. #define DATA_SEGMENT_MASK    (DATA_SEGMENT << OFFSETBITS)
  91. #define PURE_SEGMENT_MASK    (PURE_SEGMENT << OFFSETBITS)
  92. #define DUMP_SEGMENT_MASK    (DUMP_SEGMENT << OFFSETBITS)
  93. #define OFFSET_IN_DATA(X)    \
  94.     (((XPNTR((int)X) - (int)&pure)            & OFFSET_MASK) | DATA_SEGMENT_MASK)
  95. #define OFFSET_IN_PURE(X)    \
  96.     (((XPNTR((int)X) - (int)pure)            & OFFSET_MASK) | PURE_SEGMENT_MASK)
  97. #define OFFSET_IN_DUMP(X)    \
  98.     (((XPNTR((int)X) - (int)dump_vector)    & OFFSET_MASK) | DUMP_SEGMENT_MASK)
  99.     
  100. /* Just for fun */
  101. int total_fixups;
  102.  
  103. #if defined(powerc)
  104. #define DUMP_RSRC_BASE 131
  105. #else
  106. #define DUMP_RSRC_BASE 128
  107. #endif
  108.  
  109. #define STATICVEC_DUMP    DUMP_RSRC_BASE
  110. #define IMPURE_DUMP        (DUMP_RSRC_BASE+1)
  111. #define PURE_DUMP        (DUMP_RSRC_BASE+2)
  112.  
  113. static void
  114. panic(char *s)
  115. {
  116.     EventRecord e;
  117.  
  118.     printf("\012%s\012",s);
  119.     fflush(stdout);
  120.     while (!WaitNextEvent(mDownMask,&e,10,0))
  121.         ;
  122.     ExitToShell();
  123. }
  124.  
  125. static int
  126. in_pure_space(Lisp_Object p)
  127. {
  128.     p = XPNTR(p);
  129.     return p < (int)pure + PURESIZE && p >= (int)pure;
  130. }
  131.  
  132. static void *
  133. dump_alloc(int n)
  134. {
  135.     char *c;
  136.     
  137.     if (dump_free+n >= DUMP_VECTOR_MAX)
  138.         panic("dump vector overflow -- "
  139.               "need to recompile Emacs with a larger dump vector");
  140.     c = dump_vector + dump_free;
  141.     dump_free += n;
  142.     return c;
  143. }
  144.  
  145. static void
  146. spin_chores(void)
  147. {
  148.     int time;
  149.     static int last_spin_time;
  150.     
  151.     time = TickCount();
  152.     if (time != last_spin_time && (time & 15) == 0) {
  153.         last_spin_time = time;
  154.         spin_beachball();
  155.     }
  156. }
  157.  
  158. static Lisp_Object dump_one_object(Lisp_Object);
  159. static Lisp_Object restore_one_object(Lisp_Object);
  160.  
  161. static Lisp_Object
  162. dump_Lisp_String(Lisp_Object p)
  163. {
  164.     char *s;
  165.     int bytes,longwords,new;
  166.  
  167.     bytes = XSTRING(p)->size;
  168.     if (XMARKBIT(bytes)) return XUNMARK(bytes);
  169.  
  170.     longwords = ((sizeof(int) + bytes + 1) - 1) / 4 + 1;
  171.     s = dump_alloc(longwords * sizeof(int));
  172.     XSET(new,Lisp_String,OFFSET_IN_DUMP(s));
  173.     XSTRING(p)->size = new;
  174.     XMARK(XSTRING(p)->size);
  175.     *(int *)s = bytes;
  176.     memcpy(s+sizeof(int),XSTRING(p)->data,bytes);
  177.     return new;
  178. }
  179.  
  180. static Lisp_Object
  181. restore_Lisp_String(int *a)
  182. {
  183.     Lisp_Object t = a[0];
  184.     if (XMARKBIT(t)) return XUNMARK(t);
  185.     a[0] = t = make_string((char *)(a+1),*a);
  186.     XMARK(a[0]);
  187.     return t;
  188. }
  189.  
  190. static Lisp_Object
  191. dump_Lisp_Vector(Lisp_Object p)
  192. {
  193.     int *vector;
  194.     int i,new,len = XVECTOR(p)->size;
  195.     
  196.     if (XMARKBIT(len)) return XUNMARK(len);
  197.  
  198.     vector = dump_alloc((len+1) * sizeof(int));
  199.     XSET(new,XTYPE(p),OFFSET_IN_DUMP(vector));
  200.     XVECTOR(p)->size = new;
  201.     XMARK(XVECTOR(p)->size);
  202.     vector[0] = len;
  203.     for (i = 0; i<len; i++)
  204.         vector[i+1] = dump_one_object(XVECTOR(p)->contents[i]);
  205.     return new;
  206. }
  207.  
  208. static Lisp_Object
  209. restore_Lisp_Vector(int *a,int type)
  210. {
  211.     int *v,i,len,t;
  212.     len = a[0];
  213.     if (XMARKBIT(len)) return XUNMARK(len);
  214.     a[0] = XSET(t,type,Fmake_vector(len,0));
  215.     XMARK(a[0]);
  216.     v = &XVECTOR(t)->contents[0];
  217.     for (i = 0; i<len; ++i)
  218.         v[i] = restore_one_object(a[i+1]);
  219.     return t;
  220. }
  221.  
  222. static Lisp_Object
  223. dump_Lisp_Symbol(Lisp_Object p)
  224. {
  225.     int *symbol,plist,t,new;
  226.  
  227.     plist = XSYMBOL(p)->plist;
  228.     if (XMARKBIT(plist)) return XUNMARK(plist);
  229.  
  230.     symbol = dump_alloc(5*sizeof(int));
  231.     XSET(new,Lisp_Symbol,OFFSET_IN_DUMP(symbol));
  232.     XSYMBOL(p)->plist = new;
  233.     XMARK(XSYMBOL(p)->plist);
  234.  
  235.     symbol[0] = dump_one_object(XSET(t,Lisp_String,XSYMBOL(p)->name));
  236.     symbol[1] = dump_one_object(XSYMBOL(p)->value);
  237.     symbol[2] = dump_one_object(XSYMBOL(p)->function);
  238.     symbol[3] = dump_one_object(plist);
  239.     if (XSYMBOL(p)->next != 0L)
  240.         symbol[4] = dump_one_object(XSET(t,Lisp_Symbol,XSYMBOL(p)->next));
  241.     else
  242.         symbol[4] = 0L;
  243.     return new;
  244. }
  245.  
  246. static Lisp_Object
  247. restore_Lisp_Symbol(int *a)
  248. {
  249.     int plist,name,t;
  250.     struct Lisp_Symbol *s;
  251.     
  252.     plist = a[3];
  253.     if (XMARKBIT(plist)) return XUNMARK(plist);
  254.     name = restore_one_object(a[0]);
  255.     a[3] = t = Fmake_symbol(name);
  256.     XMARK(a[3]);
  257.     s = XSYMBOL(t);
  258.     s->value = restore_one_object(a[1]);
  259.     s->function = restore_one_object(a[2]);
  260.     s->plist = restore_one_object(plist);
  261.     s->next = (a[4] == 0L ? 0L : XSYMBOL(restore_one_object(a[4])));
  262.     return t;
  263. }
  264.  
  265. static Lisp_Object
  266. dump_Lisp_Subr(Lisp_Object p)
  267. {
  268.     int new,*t = dump_alloc(2*sizeof(long));
  269.     char *doc = XSUBR(p)->doc;
  270.     XSET(t[0],XTYPE(p),OFFSET_IN_DATA(p));
  271.     if ((int)doc <= 0)
  272.         t[1] = (int)doc; /* Minus an offset into doc file. */
  273.     else
  274.         XSET(t[1],Lisp_Objfwd,OFFSET_IN_DATA(doc)); /* The address of a C string */
  275.     return XSET(new,Lisp_Subr,OFFSET_IN_DUMP(t));
  276. }
  277.  
  278. static Lisp_Object
  279. restore_Lisp_Subr(int *a)
  280. {
  281.     int subr = restore_one_object(a[0]);
  282.     int doc = a[1];
  283.     if (doc <= 0)
  284.         XSUBR(subr)->doc = (char *)doc; /* The offset into the DOC file */
  285.     else
  286.         XSUBR(subr)->doc = (char *)XPNTR(restore_one_object(doc)); /* In data area */
  287.     return subr;
  288. }
  289.  
  290. static Lisp_Object
  291. dump_Lisp_Cons(Lisp_Object p)
  292. {
  293.     int *cons,car,new;
  294.     
  295.     car = XCONS(p)->car;
  296.     if (XMARKBIT(car)) return XUNMARK(car);
  297.     cons = dump_alloc(2*sizeof(Lisp_Object));
  298.     XSET(new,XTYPE(p),OFFSET_IN_DUMP(cons));
  299.     XCONS(p)->car = new;
  300.     XMARK(XCONS(p)->car);
  301.     cons[0] = dump_one_object(car);
  302.     cons[1] = dump_one_object(XCONS(p)->cdr);
  303.     return new;
  304. }
  305.  
  306. static Lisp_Object
  307. restore_Lisp_Cons(int *a,int type)
  308. {
  309.     int t,car = a[0];
  310.     if (XMARKBIT(car)) return XUNMARK(car);
  311.     a[0] = XSET(t,type,Fcons());
  312.     XMARK(a[0]);
  313.     XCONS(t)->car = restore_one_object(car);
  314.     XCONS(t)->cdr = restore_one_object(a[1]);
  315.     return t;
  316. }
  317.  
  318. static Lisp_Object
  319. dump_Lisp_Buffer(Lisp_Object p)
  320. {
  321.     int new,i,t,name;
  322.     struct buffer *buffer;
  323.     
  324.     name = XBUFFER(p)->name;
  325.     if (XMARKBIT(name)) return XUNMARK(name);
  326.  
  327.     buffer = dump_alloc(sizeof(int) + sizeof(struct buffer));
  328.     XSET(new, Lisp_Buffer, OFFSET_IN_DUMP(buffer));
  329.     XBUFFER(p)->name = new;
  330.     XMARK(XBUFFER(p)->name);
  331.  
  332.     if (XBUFFER(p) == &buffer_defaults)
  333.         *(int *)(buffer+1) = XSET(t,Lisp_Buffer,OFFSET_IN_DATA(&buffer_defaults));
  334.     else if (XBUFFER(p) == &buffer_local_symbols)
  335.         *(int *)(buffer+1) = XSET(t,Lisp_Buffer,OFFSET_IN_DATA(&buffer_local_symbols));
  336.     else
  337.         *(int *)(buffer+1) = 0;
  338.  
  339.     /* We will reinitialize text.beg when reloading. */
  340.     *buffer = *XBUFFER(p);
  341.  
  342.     if (XBUFFER(p)->next != 0L)
  343.         buffer->next = (struct buffer *)dump_one_object(XSET(t,Lisp_Buffer,XBUFFER(p)->next));
  344.     else
  345.         buffer->next = 0L;
  346.  
  347.     buffer->markers = dump_one_object(XBUFFER(p)->markers);
  348.     buffer->name = dump_one_object(name);
  349.     for (i = 1; i<lisp_objects_in_buffer; ++i)
  350.         (&buffer->name)[i] = dump_one_object((&XBUFFER(p)->name)[i]);
  351.     return new;
  352. }
  353.  
  354. static Lisp_Object
  355. restore_Lisp_Buffer(int *a)
  356. {
  357.     int buffer_offset,i,t;
  358.     struct buffer *buffer_dst;
  359.     struct buffer *buffer_src;
  360.     int name;
  361.  
  362.     buffer_src = (struct buffer *)a;
  363.     name = buffer_src->name;
  364.     if (XMARKBIT(name)) return XUNMARK(name);
  365.     
  366.     buffer_offset = *(int *)(buffer_src+1);
  367.     if (buffer_offset != 0L)
  368.         buffer_dst = XBUFFER(restore_one_object(buffer_offset));
  369.     else
  370.         buffer_dst = (struct buffer *)malloc(sizeof(struct buffer));
  371.  
  372.     buffer_src->name = XSET(t,Lisp_Buffer,buffer_dst);
  373.     XMARK(buffer_src->name);
  374.  
  375.     *buffer_dst = *buffer_src;
  376.     buffer_dst->text.beg = (unsigned char *)malloc(50); /* How do we make sure this is enough? */
  377.     if (buffer_src->next != 0L)
  378.         buffer_dst->next = XBUFFER(restore_one_object((int)buffer_src->next));
  379.     buffer_dst->markers = restore_one_object(buffer_src->markers);
  380.     buffer_dst->name = restore_one_object(name);
  381.     for (i = 1; i<lisp_objects_in_buffer; ++i)
  382.         (&buffer_dst->name)[i] = restore_one_object((&buffer_src->name)[i]);
  383.     return t;
  384. }
  385.  
  386. static Lisp_Object
  387. dump_Lisp_Marker(Lisp_Object p)
  388. {
  389.     int chain,t,new,*marker;
  390.     struct buffer *buffer;
  391.     
  392.     chain = XMARKER(p)->chain;
  393.     if (XMARKBIT(chain)) return XUNMARK(chain);
  394.  
  395.     marker = dump_alloc(3 * sizeof(int));
  396.     XSET(new,Lisp_Marker,OFFSET_IN_DUMP(marker));
  397.     XMARKER(p)->chain = new;
  398.     XMARK(XMARKER(p)->chain);
  399.     buffer = XMARKER(p)->buffer;
  400.     if (buffer != 0L)
  401.         marker[0] = dump_one_object(XSET(t,Lisp_Buffer,buffer));
  402.     else
  403.         marker[0] = 0L;
  404.     marker[1] = dump_one_object(chain);
  405.     marker[2] = XMARKER(p)->bufpos;
  406.     return new;
  407. }
  408.  
  409. static Lisp_Object
  410. restore_Lisp_Marker(int *a)
  411. {
  412.     int t,chain = a[1];
  413.     if (XMARKBIT(chain)) return XUNMARK(chain);
  414.     a[1] = t = Fmake_marker();
  415.     XMARK(a[1]);
  416.     XMARKER(t)->buffer = (a[0] == 0L ? 0L : XBUFFER(restore_one_object(a[0])));
  417.     XMARKER(t)->chain = restore_one_object(chain);
  418.     XMARKER(t)->bufpos = a[2];
  419.     ++total_fixups;
  420.     return t;
  421. }
  422.  
  423. static Lisp_Object
  424. dump_Lisp_Intfwd(Lisp_Object p)
  425. {
  426.     /*    The problem with forwarded integers is that they can be assigned -1,
  427.         for example, and with that assignment all bits are set, not just the
  428.         bits for a regular lisp integer.  So these values have no mark bit.
  429.         Thus every reference to a forwarded object gets its own description. */
  430.  
  431.     int new,*a = dump_alloc(2 * sizeof(int));
  432.     XSET(a[0],XTYPE(p),OFFSET_IN_DATA(p));
  433.     a[1] = *(int *)XPNTR(p);
  434.     return XSET(new,XTYPE(p),OFFSET_IN_DUMP(a));
  435. }
  436.  
  437. static Lisp_Object
  438. restore_Lisp_Intfwd(int *a)
  439. {
  440.     Lisp_Object t = restore_one_object(a[0]); /* a[0] is an offset into data segment */
  441.     *(int *)XPNTR(t) = a[1];
  442.     return t;
  443. }
  444.  
  445. static Lisp_Object
  446. dump_one_object(Lisp_Object p)
  447. {
  448.     int new,car,i,size;
  449.     
  450.     spin_chores();
  451.     
  452.     if (XTYPE(p) == Lisp_Int)
  453.         return p;
  454.     
  455.     if (in_pure_space(p)) {
  456.         XSET(new,XTYPE(p),OFFSET_IN_PURE(p));
  457.  
  458.         switch (XTYPE(p)) {
  459.         case Lisp_String:
  460.             return new;
  461.         case Lisp_Cons:
  462.             car = XCONS(p)->car;
  463.             if (!XMARKBIT(car)) {
  464.                 XMARK(XCONS(p)->car);
  465.                 XCONS(p)->car = dump_one_object(car);
  466.                 XMARK(XCONS(p)->car);
  467.                 XCONS(p)->cdr = dump_one_object(XCONS(p)->cdr);
  468.             }
  469.             return new;
  470.         case Lisp_Vector:
  471.             size = XVECTOR(p)->size;
  472.             if (!XMARKBIT(size)) {
  473.                 XMARK(XVECTOR(p)->size);
  474.                 for (i = 0; i<size; ++i)
  475.                     XVECTOR(p)->contents[i] = dump_one_object(XVECTOR(p)->contents[i]);
  476.             }
  477.             return new;
  478.         default:
  479.             panic("Unsupported lisp object found while dumping static objects");
  480.         }
  481.     }
  482.     
  483.     switch (XTYPE(p)) {
  484.     case Lisp_Intfwd:
  485.     case Lisp_Boolfwd:
  486.         return dump_Lisp_Intfwd(p);
  487.     case Lisp_Buffer_Objfwd:
  488.         return p;
  489.     case Lisp_String:
  490.         return dump_Lisp_String(p);
  491.     case Lisp_Symbol:
  492.         return dump_Lisp_Symbol(p);
  493.     case Lisp_Objfwd:
  494.         return XSET(new,XTYPE(p),OFFSET_IN_DATA(p));
  495.     case Lisp_Subr:
  496.         return dump_Lisp_Subr(p);
  497.     case Lisp_Cons:
  498.     case Lisp_Buffer_Local_Value:
  499.         return dump_Lisp_Cons(p);
  500.     case Lisp_Vector:
  501.     case Lisp_Window:
  502.         return dump_Lisp_Vector(p);
  503.     case Lisp_Buffer:
  504.         return dump_Lisp_Buffer(p);
  505.     case Lisp_Marker:
  506.         return dump_Lisp_Marker(p);
  507.     default:
  508.         panic("Unsupported lisp object found while dumping static objects");
  509.     }
  510. }
  511.  
  512. static void
  513. dump_all_objects(void)
  514. {
  515.     int i,p;
  516.     struct buffer *b;
  517.  
  518.     for (i = 0; i<staticidx; ++i) {
  519.         dumped_staticvec[i].object = dump_one_object(*staticvec[i]);
  520.         dumped_staticvec[i].address = OFFSET_IN_DATA(staticvec[i]);
  521.     }
  522.  
  523.     for (i = 0; i<nglobals_to_save; ++i)
  524.         dumped_staticvec[staticidx+i].object =
  525.             dump_one_object(globals_to_save[i].untagged ?
  526.                 XSET(p,globals_to_save[i].tag,*globals_to_save[i].address) :
  527.                 *globals_to_save[i].address);
  528.  
  529.     b = dump_alloc(sizeof(struct buffer));
  530.     *b = buffer_local_flags;
  531.     dumped_staticvec[staticidx + nglobals_to_save].address = OFFSET_IN_DUMP(b);
  532. }
  533.  
  534. void
  535. map_out_data()
  536. {
  537.     Handle h1,h2,h3;
  538.     short refNum,err,errpt;
  539.     char **dump_vector_handle;
  540.     struct dumped_address_and_object **dumped_staticvec_handle;
  541.     char **pure_handle;
  542.     
  543.     dump_vector_handle = NewHandle(DUMP_VECTOR_MAX);
  544.     err = MemError(); if (err) { errpt = 0; goto error; }
  545.     dumped_staticvec_handle = (struct dumped_address_and_object **)
  546.         NewHandle(sizeof(struct dumped_address_and_object) *
  547.         (staticidx+nglobals_to_save+1));
  548.     err = MemError(); if (err) { errpt = 1; goto error; }
  549.  
  550.     /* loadup.el says we are dumping into a data file. */
  551.     printf("Disregard that last message!  Dumping into resource fork.\012");
  552.     printf("Compacting...");
  553.     fflush(stdout);
  554.  
  555.     HLock((Handle)dump_vector_handle);
  556.     HLock((Handle)dumped_staticvec_handle);
  557.     dump_vector = *dump_vector_handle;
  558.     dumped_staticvec = *dumped_staticvec_handle;
  559.     dump_free = 0;
  560.     dump_all_objects();
  561.  
  562.     printf("done.\012Writing out new resources...");
  563.     fflush(stdout);
  564.  
  565.     HUnlock(dump_vector_handle);
  566.     HUnlock((Handle)dumped_staticvec_handle);
  567.     pure_handle = RecoverHandle(pure);
  568.     HUnlock(pure_handle);
  569.     SetHandleSize(dump_vector_handle,dump_free);
  570.  
  571.     /* Remove the old resources. */
  572.     SetResLoad(0);
  573.     h1 = GetResource('Dump',STATICVEC_DUMP);
  574.     h2 = GetResource('Dump',IMPURE_DUMP);
  575.     h3 = GetResource('Dump',PURE_DUMP);
  576.     SetResLoad(1);
  577.     if (h1) RmveResource(h1), DisposHandle(h1);
  578.     if (h2) RmveResource(h2), DisposHandle(h2);
  579.     if (h3) RmveResource(h3), DisposHandle(h3);
  580.  
  581.     /* Add in the new ones. */
  582.     AddResource((Handle)dumped_staticvec_handle,'Dump',STATICVEC_DUMP,0L);
  583.     err = ResError(); if (err) { errpt = 2; goto error; }
  584.     AddResource(dump_vector_handle,'Dump',IMPURE_DUMP,0L);
  585.     err = ResError(); if (err) { errpt = 3; goto error; }
  586.     AddResource(pure_handle,'Dump',PURE_DUMP,0L);
  587.     err = ResError(); if (err) { errpt = 4; goto error; }
  588.  
  589.     /* Force out the changes. */
  590.     refNum = HomeResFile((Handle)dumped_staticvec_handle);
  591.     err = ResError(); if (err) { errpt = 5; goto error; }
  592.     UpdateResFile(refNum);
  593.     err = ResError(); if (err) { errpt = 6; goto error; }
  594.  
  595.     printf("done.");
  596.     fflush(stdout);
  597.  
  598.     /* We quit here.  We can't return to the interpreter with
  599.        all the changes in the data. */
  600.  
  601.     ExitToShell();
  602.     
  603.     error:
  604.     printf("Error %d at point %d\012",err,errpt);
  605.     panic("Not enough memory or disk space to create new image -- "
  606.             "restart with a larger partition or free some disk space");
  607. }
  608.  
  609. static Lisp_Object
  610. restore_one_object(Lisp_Object p)
  611. {
  612.     int i,size,car,offset,*a,type;
  613.     register Lisp_Object t;
  614.     
  615.     spin_chores();
  616.     
  617.     type = XTYPE(p);
  618.     if (type == Lisp_Int) return p;
  619.     offset = OFFSET(p);
  620.  
  621.     switch (SEGMENT(p)) {
  622.     case NO_SEGMENT:
  623.         return p;
  624.     case DATA_SEGMENT:
  625.         ++total_fixups;
  626.         return XSET(t,type,(int)((char *)&pure + offset));
  627.     case PURE_SEGMENT:
  628.         ++total_fixups;
  629.         XSET(t,type,(int)((char *)pure + offset));
  630.         switch (type) {
  631.         case Lisp_String:
  632.             return t;
  633.         case Lisp_Vector:
  634.             size = XVECTOR(t)->size;
  635.             if (XMARKBIT(size)) {
  636.                 XUNMARK(XVECTOR(t)->size);
  637.                 size = XVECTOR(t)->size;
  638.                 for (i = 0; i<size; ++i)
  639.                     XVECTOR(t)->contents[i] = restore_one_object(XVECTOR(t)->contents[i]);
  640.             }
  641.             return t;
  642.         case Lisp_Cons:
  643.             car = XCONS(t)->car;
  644.             if (XMARKBIT(XCONS(t)->car)) {
  645.                 XUNMARK(XCONS(t)->car);
  646.                 XCONS(t)->car = restore_one_object(XCONS(t)->car);
  647.                 XCONS(t)->cdr = restore_one_object(XCONS(t)->cdr);
  648.             }
  649.             return t;
  650.         default:
  651.             panic("Unsupported lisp object found in restore_one_object");
  652.         }
  653.     case DUMP_SEGMENT:
  654.         ++total_fixups;
  655.         a = (int *)(dump_vector + offset);
  656.     
  657.         switch (type) {
  658.         case Lisp_Intfwd:
  659.         case Lisp_Boolfwd:
  660.             return restore_Lisp_Intfwd(a);
  661.         case Lisp_String:
  662.             return restore_Lisp_String(a);
  663.         case Lisp_Subr:
  664.             return restore_Lisp_Subr(a);
  665.         case Lisp_Cons:
  666.         case Lisp_Buffer_Local_Value:
  667.             return restore_Lisp_Cons(a,type);
  668.         case Lisp_Vector:
  669.         case Lisp_Window:
  670.             return restore_Lisp_Vector(a,type);
  671.         case Lisp_Symbol:
  672.             return restore_Lisp_Symbol(a);
  673.         case Lisp_Buffer:
  674.             return restore_Lisp_Buffer(a);
  675.         case Lisp_Marker:
  676.             return restore_Lisp_Marker(a);
  677.         default:
  678.             panic("Unsupported lisp object found while restoring dumped data");
  679.         }
  680.     }
  681. }
  682.  
  683. static void
  684. load_and_fixup_dump()
  685. {
  686.     int i,address,offset;
  687.     struct buffer *b;
  688.     
  689.     for (i = 0; i<staticidx; ++i) {
  690.         address = OFFSET(dumped_staticvec[i].address);
  691.         staticvec[i] = (Lisp_Object *)((char *)&pure + address);
  692.         *staticvec[i] = restore_one_object(dumped_staticvec[i].object);
  693.         ++total_fixups;
  694.     }
  695.     
  696.     for (i = 0; i<nglobals_to_save; ++i) {
  697.         *globals_to_save[i].address =
  698.             restore_one_object(dumped_staticvec[staticidx+i].object);
  699.         if (globals_to_save[i].untagged)
  700.             *globals_to_save[i].address =
  701.                 globals_to_save[i].tag == Lisp_Int ?
  702.                     XINT(*globals_to_save[i].address) :
  703.                     XUINT(*globals_to_save[i].address);
  704.         ++total_fixups;
  705.     }
  706.  
  707.     offset = OFFSET(dumped_staticvec[staticidx + nglobals_to_save].address);
  708.     b = (struct buffer *)(dump_vector + offset);
  709.     buffer_local_flags = *b;
  710.     ++total_fixups;
  711. }
  712.  
  713. void
  714. reverse_unexec(void)
  715. {
  716.     Handle h1,h2,h3;
  717.  
  718.     h1 = GetResource('Dump',STATICVEC_DUMP);
  719.     h2 = GetResource('Dump',IMPURE_DUMP);
  720.     h3 = GetResource('Dump',PURE_DUMP);
  721.     if (h1 == 0L || h2 == 0L || h3 == 0L) panic("Can't find dumped data.\012"
  722.         "Rerun Emacs holding down the option key at startup.");
  723.  
  724.     MoveHHi(h1); HLock(h1); HNoPurge(h1);
  725.     MoveHHi(h2); HLock(h2); HNoPurge(h2);
  726.     MoveHHi(h3); HLock(h3); HNoPurge(h3);
  727.  
  728.     dumped_staticvec = (struct dumped_address_and_object *)*h1;
  729.     staticidx = GetHandleSize(h1) / sizeof(struct dumped_address_and_object)
  730.         - nglobals_to_save - 1;
  731.     dump_vector = StripAddress(*h2);
  732.     dump_free = GetHandleSize(h2);
  733.     pure = StripAddress(*h3);
  734.     
  735.     load_and_fixup_dump();
  736.  
  737.     HUnlock(h1); HPurge(h1); ReleaseResource(h1);
  738.     HUnlock(h2); HPurge(h2); ReleaseResource(h2);
  739. }
  740.